/*
 *  Copyright 2004 Blandware (http://www.blandware.com)
 *
 *  Licensed under the Apache License, Version 2.0 (the "License");
 *  you may not use this file except in compliance with the License.
 *  You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 *  Unless required by applicable law or agreed to in writing, software
 *  distributed under the License is distributed on an "AS IS" BASIS,
 *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 *  See the License for the specific language governing permissions and
 *  limitations under the License.
 */
package com.blandware.atleap.common.util;

import java.text.DateFormat;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.Locale;
import java.util.HashMap;


/**
 * <p>Date Utility Class.
 * This is used to convert Strings to Dates and Timestamps and vice versa.
 * </p>
 * <p><a href="DateUtil.java.html"><i>View Source</i></a>
 * </p>
 *
 * @author Matt Raible <a href="mailto:matt@raibledesigns.com">&lt;matt@raibledesigns.com&gt;</a>
 * @author Sergey Zubtsovskiy <a href="mailto:sergey.zubtsovskiy@blandware.com">&lt;sergey.zubtsovskiy@blandware.com&gt;</a>
 * @author Roman Puchkovskiy <a href="mailto:roman.puchkovskiy@blandware.com">
 *         &lt;roman.puchkovskiy@blandware.com&gt;</a>
 * @version $Revision: 1.12 $ $Date: 2008/01/14 10:59:49 $
 */
public class DateUtil {
    //~ Static fields/initializers =============================================

    protected static String datePattern = "MM/dd/yyyy";
    protected static HashMap patterns = new HashMap();


    //~ Methods ================================================================

    /**
     * Formats given date according to specified locale and date style
     *
     * @param date      Date to convert
     * @param locale    Locale to use for formatting date
     * @param dateStyle Date style
     * @return String representation of date according to given locale and date style
     * @see java.text.DateFormat
     */
    public static String formatDate(Date date, Locale locale, int dateStyle) {
        DateFormat formatter = DateFormat.getDateInstance(dateStyle, locale);
        return formatter.format(date);
    }

    /**
     * Formats given date according to specified locale and <code>DateFormat.MEDIUM</code> style
     *
     * @param date   Date to convert
     * @param locale Locale to use for formatting date
     * @return String representation of date according to given locale and <code>DateFormat.MEDIUM</code> style
     * @see java.text.DateFormat
     * @see java.text.DateFormat#MEDIUM
     */
    public static String formatDate(Date date, Locale locale) {
        return formatDate(date, locale, DateFormat.MEDIUM);
    }

    /**
     * Parses given string according to specified locale and date style
     *
     * @param source    Source string to parse date from
     * @param locale    Locale to use for parsing date
     * @param dateStyle Date style
     * @return Date object corresponding to representation given in source string
     * @throws ParseException if given string could not be properly parsed according to given locale and style
     * @see java.text.DateFormat
     */
    public static Date parseDate(String source, Locale locale, int dateStyle) throws ParseException {
        DateFormat formatter = DateFormat.getDateInstance(dateStyle, locale);
        return formatter.parse(source);
    }

    /**
     * Parses given string according to specified locale and <code>DateFormat.MEDIUM</code> style
     *
     * @param source Source string to parse date from
     * @param locale Locale to use for parsing date
     * @return Date object corresponding to representation given in source string
     * @throws ParseException if given string could not be properly parsed according to given locale and <code>DateFormat.MEDIUM</code> style
     * @see java.text.DateFormat
     * @see java.text.DateFormat#MEDIUM
     */
    public static Date parseDate(String source, Locale locale) throws ParseException {
        return parseDate(source, locale, DateFormat.MEDIUM);
    }


    /**
     * Formats given time according to specified locale and time style
     *
     * @param time      Time to convert
     * @param locale    Locale to use for formatting time
     * @param timeStyle Time style
     * @return String representation of time according to given locale and time style
     * @see java.text.DateFormat
     */
    public static String formatTime(Date time, Locale locale, int timeStyle) {
        DateFormat formatter = DateFormat.getTimeInstance(timeStyle, locale);
        return formatter.format(time);
    }

    /**
     * Formats given time according to specified locale and <code>DateFormat.MEDIUM</code> style
     *
     * @param time   Time to convert
     * @param locale Locale to use for formatting time
     * @return String representation of time according to given locale and <code>DateFormat.MEDIUM</code> style
     * @see java.text.DateFormat
     * @see java.text.DateFormat#MEDIUM
     */
    public static String formatTime(Date time, Locale locale) {
        return formatTime(time, locale, DateFormat.MEDIUM);
    }

    /**
     * Parses given string according to specified locale and time style
     *
     * @param source    Source string to parse time from
     * @param locale    Locale to use for parsing time
     * @param timeStyle Time style
     * @return Time object corresponding to representation given in source string
     * @throws ParseException if given string could not be properly parsed according to given locale and style
     * @see java.text.DateFormat
     */
    public static Date parseTime(String source, Locale locale, int timeStyle) throws ParseException {
        DateFormat formatter = DateFormat.getTimeInstance(timeStyle, locale);
        return formatter.parse(source);
    }

    /**
     * Parses given string according to specified locale and <code>DateFormat.MEDIUM</code> style
     *
     * @param source Source string to parse time from
     * @param locale Locale to use for parsing time
     * @return Time object corresponding to representation given in source string
     * @throws ParseException if given string could not be properly parsed according to given locale and <code>DateFormat.MEDIUM</code> style
     * @see java.text.DateFormat
     * @see java.text.DateFormat#MEDIUM
     */
    public static Date parseTime(String source, Locale locale) throws ParseException {
        return parseTime(source, locale, DateFormat.MEDIUM);
    }

    /**
     * Formats given date and time according to specified locale and date style
     *
     * @param date      Date object to convert
     * @param locale    Locale to use for formatting date and time
     * @param dateStyle Date style
     * @param timeStyle Time style
     * @return String representation of date and time according to given locale and date style
     * @see java.text.DateFormat
     */
    public static String formatDateTime(Date date, Locale locale, int dateStyle, int timeStyle) {
        DateFormat formatter = DateFormat.getDateTimeInstance(dateStyle, timeStyle, locale);
        return formatter.format(date);
    }

    /**
     * Formats given date and time according to specified locale and <code>DateFormat.MEDIUM</code> style
     *
     * @param date   Date object to convert
     * @param locale Locale to use for formatting date and time
     * @return String representation of date and time according to given locale and <code>DateFormat.MEDIUM</code> style
     * @see java.text.DateFormat
     * @see java.text.DateFormat#MEDIUM
     */
    public static String formatDateTime(Date date, Locale locale) {
        return formatDateTime(date, locale, DateFormat.MEDIUM, DateFormat.MEDIUM);
    }

    /**
     * Parses given string according to specified locale and date and time styles
     *
     * @param source    Source string to parse date and time from
     * @param locale    Locale to use for parsing date and time
     * @param dateStyle Date style
     * @param timeStyle Time style
     * @return Date object corresponding to representation given in source string
     * @throws ParseException if given string could not be properly parsed according to given locale and style
     * @see java.text.DateFormat
     */
    public static Date parseDateTime(String source, Locale locale, int dateStyle, int timeStyle) throws ParseException {
        DateFormat formatter = DateFormat.getDateTimeInstance(dateStyle, timeStyle, locale);
        return formatter.parse(source);
    }

    /**
     * Parses given string according to specified locale and <code>DateFormat.MEDIUM</code> style
     *
     * @param source Source string to parse date and time from
     * @param locale Locale to use for parsing date and time
     * @return Date object corresponding to representation given in source string
     * @throws ParseException if given string could not be properly parsed according to given locale and <code>DateFormat.MEDIUM</code> style
     * @see java.text.DateFormat
     * @see java.text.DateFormat#MEDIUM
     */
    public static Date parseDateTime(String source, Locale locale) throws ParseException {
        return parseDateTime(source, locale, DateFormat.MEDIUM, DateFormat.MEDIUM);
    }

    /**
     * Formats given Date object according to specified locale and a given
     * pattern.
     *
     * @param date   Date object to convert
     * @param locale Locale to use for formatting
     * @param pattern Pattern to use
     * @return String representation of date and time according to given locale and <code>DateFormat.MEDIUM</code> style
     * @see java.text.SimpleDateFormat
     */
    public static String format(Date date, Locale locale, String pattern) {
        SimpleDateFormat formatter = new SimpleDateFormat(pattern, locale);
        return formatter.format(date);
    }

    /**
     * Parses given string according to specified locale and a given pattern.
     *
     * @param source Source string to parse date and time from
     * @param locale Locale to use for parsing date and time
     * @param pattern Pattern to use
     * @return Date object corresponding to representation given in source
     * string
     * @throws ParseException if given string could not be properly parsed
     * according to given locale and pattern
     * @see java.text.SimpleDateFormat
     */
    public static Date parse(String source, Locale locale, String pattern)
            throws ParseException {
        SimpleDateFormat formatter = new SimpleDateFormat(pattern, locale);
        return formatter.parse(source);
    }

    /**
     * Returns default datePattern (MM/dd/yyyy)
     *
     * @return a string representing the date pattern on the UI
     */
    public static String getDatePattern() {
        return datePattern;
    }

    /**
     * Gets date pattern without time symbols according to given locale and date style
     *
     * @param locale    Locale to searh pattern for
     * @param dateStyle Date style to search pattern by
     * @return Date pattern without time symbols
     */
    public static String getDatePattern(Locale locale, int dateStyle) {
        String id = locale.toString() + "+" + dateStyle;
        String pattern = (String) patterns.get(id);
        if (pattern == null) {
            SimpleDateFormat format = (SimpleDateFormat) DateFormat.getDateInstance(dateStyle, locale);
            pattern = format.toPattern();
            patterns.put(id, pattern);
        }
        return pattern;
    }

    /**
     * Gets date pattern without time symbols according to given locale in MEDIUM style
     *
     * @param locale Locale to searh pattern for
     * @return Date pattern without time symbols in medium format
     * @see java.text.DateFormat#MEDIUM
     */
    public static String getDatePattern(Locale locale) {
        return getDatePattern(locale, DateFormat.MEDIUM);
    }
}
